package com.kdgc.power.common.util;


import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;

public class MathUtil {
    /**
     * @return true:质数   false：非质数
     */
    public static boolean isPrime(int num) {
        if (num < 2) return false;
        for (int i = 2; i <= Math.sqrt(num); i++) if (num % i == 0) return false;
        return true;
    }

    /**
     * 分解质因数  打印：  45=3^2 × 5
     */
    public static void resolve(long num) {
        System.out.print(num + " = ");
        long divisor = 2;
        while (divisor <= num) {
            if (num % divisor == 0) {
                int count = 0;
                while (num % divisor == 0) {
                    num = num / divisor;
                    count++;
                }
                System.out.print(divisor);
                if (count > 1) System.out.print("^" + count);
                if (divisor < num) System.out.print(" × ");
            } else divisor++;
        }
    }

    /**
     * 去除非数字部分后分解质因数  打印：  45 = 3^2 × 5
     */
    public static void resolve(String num) {
        String realNum = num.replaceAll("\\D", "");
        BigInteger bigInteger = new BigInteger(realNum);
        BigInteger divisor = new BigInteger("2");
        System.out.print(realNum + " = ");
        while (divisor.compareTo(bigInteger) <= 0) {
            if (bigInteger.mod(divisor).equals(BigInteger.ZERO)) {
                int count = 0;
                while (bigInteger.mod(divisor).equals(BigInteger.ZERO)) {
                    bigInteger = bigInteger.divide(divisor);
                    count++;
                }
                System.out.print(divisor);
                if (count > 1) System.out.print("^" + count);
                if (divisor.compareTo(bigInteger) < 0) System.out.print(" × ");
            } else
                divisor = divisor.add(BigInteger.ONE);
        }

    }

    /**
     * 辗转相除法 求最大公因（约）数
     *
     * @return 24，36 -> (12*2,12*3)  ->12
     */
    public static int maxCommonDivisor(int num1, int num2) {
        int temp = num2 % num1;
        while (temp > 0) {
            num2 = num1;
            num1 = temp;
            temp = num2 % num1;
        }
        return num1;
    }

    /**
     *  牛顿迭代法 开平方根 ： 4 -> 2.0   2.56 -> 1.6    2 ->1.414...
     *
     * @param num 待开平方根数字
     * @param bit 保留 bit 位小数  （最后一位以后全舍弃）
     */
    public static void sqrt(double num, int bit) {
        BigDecimal initNum = new BigDecimal(String.valueOf(num));
        BigDecimal tempResult = new BigDecimal(String.valueOf(Math.sqrt(num)));
        if (tempResult.pow(2).compareTo(initNum) == 0) {
            System.out.println(tempResult);
        } else {
            while (tempResult.pow(2).subtract(initNum).abs().compareTo(new BigDecimal("0.1").pow(bit)) > 0) {
                tempResult = initNum.divide(tempResult, bit + 1, RoundingMode.HALF_EVEN).add(tempResult).divide(BigDecimal.valueOf(2), bit + 1, RoundingMode.HALF_EVEN);
            }
            String result = tempResult.toString();
            result = result.substring(0, result.indexOf(".") + bit + 1);
            System.out.println(result);
        }
    }

    /**
     * 阶乘   4 -> 24  ( =1*2*3*4 )
     */
    public static BigInteger factorial(long num) {
        if (num < 0)
            throw new IllegalArgumentException("num must be a natural number：" + num);
        BigInteger result = BigInteger.ONE;
        for (int i = 2; i <= num; i++)
            result = result.multiply(new BigInteger(String.valueOf(i)));
        return result;
    }

    /**
     * 组合数    6,3 -> 20   (6*5*4) / (3*2*1)
     */
    public static BigInteger C(long down, long up) {
        return factorial(down).divide(factorial(down - up)).divide(factorial(up));
    }

    /**
     * 排列数  6,3 ->120  (6*5*4)
     */
    public static BigInteger A(long down, long up) {
        return factorial(down).divide(factorial(down - up));
    }

    /**
     *  生成 num 个 0 的字符串，如 num=3 时返回 "000"
     */
    public static String numberTo0(int num) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < num; i++) {
            builder.append("0");
        }
        return builder.toString();
    }
}
